/*
----------------------------------------------------------------------------
Copyright (c) 2005 - 2009, Wangxing SHI	<swxlion@gmail.com>

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above
	  copyright notice, this list of conditions and the
	  following disclaimer.

    * Redistributions in binary form must reproduce the above
	  copyright notice, this list of conditions and the following
	  disclaimer in the documentation and/or other materials
	  provided with the distribution.

    * Neither the copyright holder's name nor the names of its
	  contributors may be used to endorse or promote products
	  derived from this software without specific prior written
	  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
*/

/*-------------------- TMemoryPoolCore.windows.hpp ------------------------*/
/*===========================================================================
FILE: TMemoryPoolCore.windows.hpp
Author: Wangxing SHI (swxlion)
Version: 0.4.2
Date: 2009-06-28

File Description:
    C++ template for Memory Pool.

Dependencies:
    Platform: Microsoft Windows Series OS.

Notice:
    The default constructor without parameters of type T must be provided. If want
	to call the constructor with parameters, please USE new(p) for calling the
	constructor after memory block gained, because the memory pool can't know the
	parameters of constructor.
	(The memory pool will call the default constructor and destructor for type T
	automatically when gainning and recycling operations.)

History:
    version        author        date       description
	----------------------------------------------------
	0.3.3          swxlion       06-07-30   The lastest version of MemoryManage.
	0.3.4          swxlion       08-04-07   Integrated in the ASDL namespace.
	0.4.0          swxlion       08-04-13   Add the perfect limitation.
	0.4.1          swxlion       08-04-17   Release as the stadnard edition core.
	0.4.2          swxlion       09-06-28   Integrated to Luna Log.
===========================================================================*/
#ifndef _LUNA_LOG__TMEMORY_POOL_CORE_H_
#define _LUNA_LOG__TMEMORY_POOL_CORE_H_

//-- #include "PlatformDefinition.h"
#include "inc/WindowsPlatform.inc"
/*===============================================================================
INCLUDES AND VARIABLE DEFINITIONS
=============================================================================== */
#include <new>
#include <windows.h>
#include "MemoryPoolHelper.hpp"
#include "ITMemoryPool.hpp"
#include "Constant.hpp"
#include "ErrorCode.hpp"

/*===============================================================================
  CLASS & STRUCTURE DEFINITIONS
=============================================================================== */
namespace LunaLog
{
	template < typename K >
	class TMemoryPoolCore: public ITMemoryPool<K>
	{
	private:
		HANDLE				hHeap;
		HANDLE				hAssistantHeap;

		MemoryData<K>*		pRecycleLink;
		MemoryData<K>*		pActiveLink;		//-- Only for calling destructor.
		MemoryData<K>*		pActiveOverdraftLink;	//-- Only for call destructor.
		ULONG				ulMaxNum;
		ULONG				ulIncNum;			//-- The number of added blocks in each appending operation.
		ULONG				ulPerfectNum;

		ULONG				ulUsedNum;			//-- Not include the Overdraft nodes.
		ULONG				ulFreeNum;
		ULONG				ulOverdraftNumber;
		ULONG				ulTotalNum;

		bool				bInited;

	private:
		template <typename T>
		bool InitSptHeap( HANDLE hHeap, T** ppLinkHead, size_t size, ULONG ulNumber );

		template <typename T>
		T* GainNode( T** ppRecycleLinkHead, T** ppActiveLinkHead );

		template <typename T>
		void RecycleNode( T** ppRecycleLinkHead, T** ppActiveLinkHead, T** ppNode );

		template <typename T>
		void RecycleOverdraftNode( HANDLE hHeap, T** ppActiveOverdraftLinkHead, T** ppNode );

		template <typename T>
		URESULT AppendNode( HANDLE hHeap, T** ppLinkHead, size_t size, ULONG ulNumber );

		template <typename T>
		T* AppendOverdraftNode( HANDLE hHeap, T** ppActiveOverdraftLinkHead, size_t size );

		URESULT Append( ULONG ulNumber, MemoryData<K>** ppOverdraftNode );

		template <typename T>
		T CalculateHeapCreateSize( T sizeHeapHeadSize, T sizeBlockSize, T BlockNumber );

		bool CreateHeap( ULONG ulInitNumber );
		bool CreateHeap( HANDLE &hHeap, size_t sizeInitialSize, size_t sizeMaximumSize );
		void InitHeap( ULONG ulNumber );

		void ReviseDataRelation( ULONG ulInitNum );
		void DestructTypeUnit( MemoryData<K>* pActiveLink );
		void DestroyHeap( HANDLE & hHeap);

	protected:
		MemoryData<K>* GainOriginal();						//- Gain the memory block.
		void Recycle( MemoryData<K>** ppNode );				//- Recycle the memory block.

	public:
		TMemoryPoolCore(): hHeap(0),hAssistantHeap(0),
			pRecycleLink(0), pActiveLink(0), pActiveOverdraftLink(0),
			ulMaxNum(LunaLog::Constant::MemoryPool::gc_ulMaxNum),
			ulIncNum(LunaLog::Constant::MemoryPool::gc_ulIncNum),
			ulPerfectNum(LunaLog::Constant::MemoryPool::gc_ulPerfectNum),
			ulUsedNum(0), ulFreeNum(0), ulOverdraftNumber(0), ulTotalNum(0), bInited(false)
		{
		}

		~TMemoryPoolCore()
		{
			Free();
		}

		virtual bool Init( ULONG ulInitNumber = LunaLog::Constant::MemoryPool::gc_ulInitNum,
					  ULONG ulMaxNumber = LunaLog::Constant::MemoryPool::gc_ulMaxNum,
					  ULONG ulPerIncNumber = LunaLog::Constant::MemoryPool::gc_ulIncNum,
					  ULONG ulPerfectNumber = LunaLog::Constant::MemoryPool::gc_ulPerfectNum );
		virtual void Free();

		virtual K* Gain();											//- Gain the memory block.
		virtual void Recycle( K** ppNode );							//- Recycle the memory block.
		virtual void Recycle( K* & pNode );							//- Recycle the memory block.

		virtual bool IsInited()
		{
			return bInited;
		}

		virtual void GetStatus( MemoryPoolStatus &strMPS );
		virtual void GetStatusSnapshot( MemoryPoolStatus &strMPS );
	};
}

/*===============================================================================
FUNCTION DEFINITIONS: General Size Fixed Memory Pool Functions
=============================================================================== */
/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::InitSptHeap

DESCRIPTION:
  Initialize the specified heap.

PARAMETERS:
	hHeap [in] - Handle to the heap to be initialized.
	ppLinkHead [in] - The pointer point to the head pointer of recycle list belonged to a specified heap.
	size [in] - Size of memory block.
	ulNumber [in] - The number for memory block allocation after the specified heap created.

RETURN VALUE:
   true - All blocks which are required in initialization are initialized.
   false - Not all blocks which are required in initialization are initialized.
===========================================================================*/
template <typename K>
template <typename T>
bool LunaLog::TMemoryPoolCore<K>::InitSptHeap( HANDLE hHeap, T** ppLinkHead, size_t size, ULONG ulNumber )
{
	if( !hHeap )
		return false;

	ULONG	ulFailedCounter = 0;

	ulUsedNum = 0;
	ulFreeNum = 0;
	ulTotalNum = 0;

	T*			pPointer = NULL;

	while( *ppLinkHead )
	{
		pPointer = *ppLinkHead;
		*ppLinkHead = (*ppLinkHead)->Next;
		HeapFree( hHeap, 0, pPointer );
	}
	for( ULONG ul = 0; ul < ulNumber; ul++ )
	{
		pPointer = reinterpret_cast<T*>( HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size ) );
		if( !pPointer )
		{
			ulFailedCounter += 1;
			continue;
		}
		if( *ppLinkHead )
		{
			(*ppLinkHead)->Pre = pPointer;
			pPointer->Next = *ppLinkHead;
		}
		else
			pPointer->Next = NULL;

		pPointer->Pre = NULL;
		*ppLinkHead = pPointer;
	}

	ulFreeNum = ulNumber - ulFailedCounter;
	ulTotalNum = ulNumber - ulFailedCounter;

	if( ulFailedCounter == 0 )
		return true;
	else
		return false;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::GainNode

DESCRIPTION:
  Gain the available node from memory buffer.

PARAMETERS:
	ppRecycleLinkHead [in] - The pointer point to the head pointer of recycle list belonged to a specified heap.
	ppActiveLinkHead [in] - The pointer point to the head pointer of active list belonged to a specified heap.

RETURN VALUE:
   T* - Succeed;
   NULL - Failed.
===========================================================================*/
template <typename K>
template <typename T>
T*  LunaLog::TMemoryPoolCore<K>::GainNode( T** ppRecycleLinkHead, T** ppActiveLinkHead )
{
	T*	pPointer = NULL;

	pPointer = *ppRecycleLinkHead;
	if( !pPointer )
		return NULL;

	*ppRecycleLinkHead = (*ppRecycleLinkHead)->Next;
	if( *ppRecycleLinkHead )
		(*ppRecycleLinkHead)->Pre = NULL;

	//-- Active Link
	pPointer->Pre = NULL;
	pPointer->Next = *ppActiveLinkHead;
	if( *ppActiveLinkHead )
		(*ppActiveLinkHead)->Pre = pPointer;
	*ppActiveLinkHead = pPointer;

	ulUsedNum += 1;
	ulFreeNum -= 1;

	new((K*)pPointer) K;
	return pPointer;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::RecycleNode

DESCRIPTION:
  Recycle memory block, and hang it over the recycle list. 

PARAMETERS:
	ppRecycleLinkHead [in] - The pointer point to the head pointer of recycle list belonged to a specified sub pool.
	ppActiveLinkHead [in] - The pointer point to the head pointer of active list belonged to a specified sub pool.
	ppNode [in] - The block will be recycled.

RETURN VALUE:
   None
===========================================================================*/
template <typename K>
template <typename T>
void LunaLog::TMemoryPoolCore<K>::RecycleNode( T** ppRecycleLinkHead, T** ppActiveLinkHead, T** ppNode )
{
	((K*)(*ppNode))->~K();

	//-- Active Link
	if( (*ppNode)->Pre )
		(*ppNode)->Pre->Next = (*ppNode)->Next;
	else
	{
		// *ppNode is the pActiveLinkHead.
		*ppActiveLinkHead = (*ppNode)->Next;
	}
	if( (*ppNode)->Next )
		(*ppNode)->Next->Pre = (*ppNode)->Pre;

	//-- Recycle Link
	(*ppNode)->Pre = NULL;
	(*ppNode)->Next = *ppRecycleLinkHead;
	if( *ppRecycleLinkHead )
		(*ppRecycleLinkHead)->Pre = *ppNode;
	*ppRecycleLinkHead = *ppNode;

	ulUsedNum -= 1;
	ulFreeNum += 1;

	*ppNode = NULL;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::RecycleOverdraftNode

DESCRIPTION:
  Recycle overdraft memory block. 

PARAMETERS:
	hHeap [in] - Handle to the heap to recover the memory block.
	ppActiveLinkHead [in] - The pointer point to the head pointer of active overdraft list belonged to a specified heap.
	ppNode [in] - The block will be recovered.

RETURN VALUE:
   None
===========================================================================*/
template <typename K>
template <typename T>
void LunaLog::TMemoryPoolCore<K>::RecycleOverdraftNode( HANDLE hHeap, T** ppActiveOverdraftLinkHead, T** ppNode )
{
	((K*)(*ppNode))->~K();

	//-- Active Link
	if( (*ppNode)->Pre )
		(*ppNode)->Pre->Next = (*ppNode)->Next;
	else
	{
		// *ppNode is the pActiveOverdraftLinkHead.
		*ppActiveOverdraftLinkHead = (*ppNode)->Next;
	}
	if( (*ppNode)->Next )
		(*ppNode)->Next->Pre = (*ppNode)->Pre;

	ulOverdraftNumber -= 1;
	ulTotalNum -= 1;

	HeapFree( hHeap, 0, *ppNode );

	*ppNode = NULL;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::AppendNode

DESCRIPTION:
  Append new memory blocks in the pool.

PARAMETERS:
	hHeap [in] - Handle to the heap to be append some new memory blocks.
	ppLinkHead [in] - The pointer point to the head pointer of recycle list belonged to a specified heap.
	size [in] - Size of memory block.
	ulNumber [in] - The number for memory block allocation after the specified heap created.

RETURN VALUE:
   E_SUCCESS - Succeed;
   E_MEMORY_POOL__APPEND_MEMORY - Append Failed;
===========================================================================*/
template <typename K>
template <typename T>
LunaLog::URESULT LunaLog::TMemoryPoolCore<K>::AppendNode( HANDLE hHeap, T** ppLinkHead, size_t size, ULONG ulNumber )
{
	if( !hHeap )
		return LunaLog::ErrorCode::E_MEMORY_POOL__APPEND_MEMORY;

	T*			pTempHeader = NULL;
	T*			pPointer = NULL;

	ULONG		ulCycle = 0;
	for( ; ulCycle < ulNumber; ulCycle++ )
	{
		pPointer = reinterpret_cast<T*>( HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size ) );
		if( !pPointer )
		{
			break;
		}

		pPointer->Pre = NULL;
		pPointer->Next = NULL;
		pPointer->bOverdraft = NULL;

		if( pTempHeader )
		{
			pTempHeader->Pre = pPointer;
			pPointer->Next = pTempHeader;
		}
		pTempHeader = pPointer;
	}

	if( !pTempHeader )
		return LunaLog::ErrorCode::E_MEMORY_POOL__APPEND_MEMORY;	// return 2;

	//--------------------------------
	ulFreeNum += ulCycle;
	ulTotalNum += ulCycle;

	pPointer = *ppLinkHead;
	if( *ppLinkHead )
	{
		while( pPointer->Next )
		{
			pPointer = pPointer->Next;
		}

		pPointer->Next = pTempHeader;
		pTempHeader->Pre = pPointer;
	}
	else
		*ppLinkHead = pTempHeader;

	return LunaLog::ErrorCode::E_SUCCESS;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::AppendOverdraftNode

DESCRIPTION:
  Append the overdraft memory block in the pool.

PARAMETERS:
	hHeap [in] - Handle to the heap to be append a new overdraft memory block.
	ppActiveOverdraftLinkHead [in] - The pointer point to the head pointer of active overdraft list belonged to a specified heap.

RETURN VALUE:
   T* - Succeed;
   NULL - Failed.
===========================================================================*/
template <typename K>
template <typename T>
T* LunaLog::TMemoryPoolCore<K>::AppendOverdraftNode( HANDLE hHeap, T** ppActiveOverdraftLinkHead, size_t size )
{
	if( !hAssistantHeap )
		return NULL;

	T*			pPointer = NULL;

	pPointer = reinterpret_cast<T*>( HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size ) );

	if( !pPointer )
		return NULL;

	pPointer->Pre = NULL;
	pPointer->bOverdraft = this;

	ulOverdraftNumber += 1;
	ulTotalNum += 1;

	pPointer->Next = *ppActiveOverdraftLinkHead;
	if( *ppActiveOverdraftLinkHead )
		(*ppActiveOverdraftLinkHead)->Pre = pPointer;
	*ppActiveOverdraftLinkHead = pPointer;

	return pPointer;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::Append

DESCRIPTION:
  Append new memory blocks in the pool.

PARAMETERS:
	ulNumber [in] - The number of memory blocks which will be added.
	ppOverdraftNode [out] - Output the overdraft block after the memory pool catched the perfect restriction.

RETURN VALUE:
   E_SUCCESS - Succeed;
   E_MEMORY_POOL__APPEND_MEMORY - Append Failed;
   E_MEMORY_POOL__CATCH_LIMITATION - The total number of memory blocks catched the maximum restriction of the pool.
   E_MEMORY_POOL__CATCH_PERFECT_LIMITATION - The number of standard memory blocks (not include the overdraft blocks) catched the perfect restriction of the pool.
===========================================================================*/
template <typename K>
LunaLog::URESULT LunaLog::TMemoryPoolCore<K>::Append( ULONG ulNumber, LunaLog::MemoryData<K>** ppOverdraftNode )
{
	if( ulPerfectNum == LunaLog::Constant::MemoryPool::gc_ulDisablePerfectLimitation )
	{
		if( ulMaxNum != 0 )
		{
			if( ulMaxNum == ulTotalNum )
				return LunaLog::ErrorCode::E_MEMORY_POOL__CATCH_LIMITATION;
		}
	}
	else
	{
		ULONG	ulRemainNumber = ulPerfectNum - (ulTotalNum - ulOverdraftNumber);	//-- Eliminate data dependence.

		if( ulTotalNum - ulOverdraftNumber >= ulPerfectNum )
		{
			if( ulMaxNum != 0 )
			{
				if( ulMaxNum == ulTotalNum )
					return LunaLog::ErrorCode::E_MEMORY_POOL__CATCH_LIMITATION;
			}

			*ppOverdraftNode = AppendOverdraftNode( hAssistantHeap, &pActiveOverdraftLink, sizeof( MemoryData<K> ) );

			if( *ppOverdraftNode )
				new((K*)(*ppOverdraftNode)) K;

			return LunaLog::ErrorCode::E_MEMORY_POOL__CATCH_PERFECT_LIMITATION;
		}
		else if( ulRemainNumber < ulNumber )
			ulNumber = ulRemainNumber;
	}

	return AppendNode( hHeap, &pRecycleLink, sizeof( MemoryData<K> ), ulNumber );
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::ReviseDataRelation

DESCRIPTION:
  Revise the relation of data which are used to initialize the memory pool.

PARAMETERS:
	ulInitNum [in] - The number for memory block allocation after the pool created.

RETURN VALUE:
   None.
===========================================================================*/
template <typename K>
void LunaLog::TMemoryPoolCore<K>::ReviseDataRelation( ULONG ulInitNum )
{
	if( ulMaxNum > 0 )
	{
		if( ulMaxNum < ulInitNum )
			ulMaxNum = ulInitNum;
		if( ulPerfectNum != LunaLog::Constant::MemoryPool::gc_ulDisablePerfectLimitation )
			if( ulPerfectNum > ulMaxNum )
				ulPerfectNum = ulMaxNum;
	}

	
	if( ulPerfectNum < ulInitNum )
		ulPerfectNum = ulInitNum;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::Init

DESCRIPTION:
  Initialize the memory pool.

PARAMETERS:
	ulInitNumber [in] - The number for memory block allocation after the pool created.
	ulMaxNumber [in] - The maximum number of blocks held by memory pool. If don't use the restriction, please let the value is ZERO.
	ulPerIncNumber [in] - The number of memory blocks appended in the appending operation.
	ulPerfectNumber [in] - The soft restriction. If the number of memory blocks beyond this restriction, the pool will return the 
	                       excess memories to the operating system rather than continue holding the blocks.

RETURN VALUE:
   true - Succeed;
   false - Failed.

NOTICE:
   Please ensure that It is thread safety when calling this function.
===========================================================================*/
template <typename K>
bool LunaLog::TMemoryPoolCore<K>::Init( ULONG ulInitNumber, ULONG ulMaxNumber, ULONG ulPerIncNumber, ULONG ulPerfectNumber )
{
	if( bInited )
		return true;

	ulMaxNum = ulMaxNumber;
	ulIncNum = ulPerIncNumber;
	ulPerfectNum = ulPerfectNumber;
	ReviseDataRelation( ulInitNumber );

	//-- Create Heaps.
	if( CreateHeap( ulInitNumber ) == false )
		return false;

	//-- Init Heaps.
	InitHeap( ulInitNumber );

	bInited = true;
	return true;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::InitHeap

DESCRIPTION:
  Initialize the heaps for memory pool.

PARAMETERS:
	ulNumber [in] - The number for memory block allocation after the pool initialized.

RETURN VALUE:
   None.
===========================================================================*/
template <typename K>
inline void LunaLog::TMemoryPoolCore<K>::InitHeap( ULONG ulNumber )
{
	InitSptHeap( hHeap, &pRecycleLink, sizeof( MemoryData<K> ), ulNumber );
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::CreateHeap

DESCRIPTION:
  Create the heaps for memory pool.

PARAMETERS:
	ulInitNumber [in] - The number for memory block allocation after the pool created.

RETURN VALUE:
   true - Succeed;
   false - Failed.
===========================================================================*/
template <typename K>
bool LunaLog::TMemoryPoolCore<K>::CreateHeap( ULONG ulInitNumber )
{
	size_t	sizeHeapHeadSize, sizeUnitHeadSize, sizeMinimumUnitSize;

	if( SMemoryPoolHelper::GetReference().GetHeapInsideInformation( sizeHeapHeadSize, sizeUnitHeadSize, sizeMinimumUnitSize ) == false )
		return false;

	size_t	sizeBlockSize = (sizeUnitHeadSize + sizeof(MemoryData<K>) > sizeMinimumUnitSize) ? (sizeUnitHeadSize + sizeof(MemoryData<K>)) : sizeMinimumUnitSize;

	//-- Creating main heap.
	size_t sizeMaximumSizeForCreate = 0;

	if( ulPerfectNum == 0 )
	{
		DestroyHeap( hHeap );
	}
	else
	{
		if( ulPerfectNum == LunaLog::Constant::MemoryPool::gc_ulDisablePerfectLimitation )
			sizeMaximumSizeForCreate = CalculateHeapCreateSize( sizeHeapHeadSize, sizeBlockSize, (size_t)ulMaxNum );
		else
			sizeMaximumSizeForCreate = CalculateHeapCreateSize( sizeHeapHeadSize, sizeBlockSize, (size_t)ulPerfectNum );

		if( CreateHeap( hHeap,
			CalculateHeapCreateSize( sizeHeapHeadSize, sizeBlockSize, (size_t)ulInitNumber ),
			sizeMaximumSizeForCreate ) == false )
			return false;
	}

	//-- Creating assistant heap.
	//if( ulPerfectNum == LunaLog::Constant::MemoryPool::gc_ulDisablePerfectLimitation )
	//	sizeMaximumSizeForCreate = 0;
	//else
	//	sizeMaximumSizeForCreate = CalculateHeapCreateSize( sizeHeapHeadSize, sizeBlockSize, (size_t)(ulMaxNumber - ulPerfectNumber) );

	//if( CreateHeap( hAssistantHeap,
	//	CalculateHeapCreateSize( sizeHeapHeadSize, sizeBlockSize, 0 ),
	//	sizeMaximumSizeForCreate ) == false )
	//	return false;

	if( (ulPerfectNum == ulMaxNum && ulMaxNum != 0)
		|| ((ulPerfectNum == LunaLog::Constant::MemoryPool::gc_ulDisablePerfectLimitation)
		&& ulMaxNum == 0) )
	{
		DestroyHeap( hAssistantHeap );
	}
	else
	{
		if( ulMaxNum == 0 )
			sizeMaximumSizeForCreate = 0;
		else
			sizeMaximumSizeForCreate = CalculateHeapCreateSize( sizeHeapHeadSize, sizeBlockSize, (size_t)(ulMaxNum - ulPerfectNum) );

		if( CreateHeap( hAssistantHeap,
			CalculateHeapCreateSize( sizeHeapHeadSize, sizeBlockSize, (size_t)0 ),
			sizeMaximumSizeForCreate ) == false )
			return false;
	}

	return true;
}

template <typename K>
inline bool LunaLog::TMemoryPoolCore<K>::CreateHeap( HANDLE & hHeap, size_t sizeInitialSize, size_t sizeMaximumSize )
{
	DestroyHeap( hHeap );

	hHeap = HeapCreate( 0, sizeInitialSize, sizeMaximumSize );
	if( !hHeap )
		return false;
	else
		return true;
}


template <typename K>
template <typename T>
inline T LunaLog::TMemoryPoolCore<K>::CalculateHeapCreateSize( T sizeHeapHeadSize, T sizeBlockSize, T BlockNumber )
{
	return (BlockNumber == 0) ? 0 : (sizeHeapHeadSize + sizeBlockSize * BlockNumber);
}


template <typename K>
inline void LunaLog::TMemoryPoolCore<K>::DestructTypeUnit( LunaLog::MemoryData<K>* pActiveLink )
{
	while( pActiveLink )
	{
		((K*)pActiveLink)->~K();
		pActiveLink = pActiveLink->Next;
	}
}

template <typename K>
inline void LunaLog::TMemoryPoolCore<K>::DestroyHeap( HANDLE & hHeap)
{
	if( hHeap )
	{
		HeapDestroy( hHeap );
		hHeap = NULL;
	}
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::Free

DESCRIPTION:
   Free the memory pool.

PARAMETERS:
	None

RETURN VALUE:
   None
===========================================================================*/
template <typename K>
void LunaLog::TMemoryPoolCore<K>::Free()
{
	if( bInited == false )
		return;

	DestructTypeUnit( pActiveLink );
	DestructTypeUnit( pActiveOverdraftLink );

	DestroyHeap( hHeap );
	DestroyHeap( hAssistantHeap );

	pRecycleLink = NULL;
	pActiveLink = NULL;
	pActiveOverdraftLink = NULL;

	ulUsedNum = 0;
	ulFreeNum = 0;
	ulOverdraftNumber = 0;
	ulTotalNum = 0;

	bInited = false;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::GainOriginal

DESCRIPTION:
	Function series: Gain the memory block from buffer.

PARAMETERS:
	None

RETURN VALUE:
   NULL - Failed.
   Others - Succeed.
===========================================================================*/
template <typename K>
LunaLog::MemoryData<K>* LunaLog::TMemoryPoolCore<K>::GainOriginal()
{
	using namespace LunaLog::ErrorCode;

	if( bInited == false )
		return NULL;

	MemoryData<K>*	pNode = GainNode( &pRecycleLink, &pActiveLink );
	if( !pNode )
	{
		URESULT result = Append( ulIncNum, &pNode );

		switch( result )
		{
		case E_MEMORY_POOL__CATCH_PERFECT_LIMITATION:
			return pNode;
		case E_SUCCESS:
			return GainNode( &pRecycleLink, &pActiveLink );
		default:
			return NULL;
		}
	}
	return pNode;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::Recycle

DESCRIPTION:
	Function series: Recycle memory block, and hang it over the recycle list. 

PARAMETERS:
	ppNode [in] - The block will be recycled.

RETURN VALUE:
   None
===========================================================================*/
template <typename K>
void LunaLog::TMemoryPoolCore<K>::Recycle( LunaLog::MemoryData<K>** ppNode )
{
	if( bInited == false || !ppNode || !(*ppNode) )
		return;

	if( (*ppNode)->bOverdraft != NULL )
		RecycleOverdraftNode( hAssistantHeap, &pActiveOverdraftLink, ppNode );
	else
		RecycleNode( &pRecycleLink, &pActiveLink, ppNode );
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::Gain

DESCRIPTION:
	Function series: Gain the memory block from buffer.

PARAMETERS:
	None

RETURN VALUE:
   NULL - Failed.
   Others - Succeed.
===========================================================================*/
template <typename K>
K* LunaLog::TMemoryPoolCore<K>::Gain()
{
	using namespace LunaLog::ErrorCode;

	if( bInited == false )
		return NULL;

	K*	pNode = (K*)GainNode( &pRecycleLink, &pActiveLink );
	if( !pNode )
	{
		MemoryData<K>*		pMemPoolNode = NULL;
		URESULT result = Append( ulIncNum, &pMemPoolNode );

		switch( result )
		{
		case E_MEMORY_POOL__CATCH_PERFECT_LIMITATION:
			return (K*)pMemPoolNode;
		case E_SUCCESS:
			return (K*)(GainNode( &pRecycleLink, &pActiveLink ));
		default:
			return NULL;
		}
	}
	return pNode;
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::Recycle

DESCRIPTION:
	Function series: Recycle memory block, and hang it over the recycle list.

PARAMETERS:
	pNode [in] - The block will be recycled.

RETURN VALUE:
   None
===========================================================================*/
template <typename K>
void LunaLog::TMemoryPoolCore<K>::Recycle( K** ppNode )
{
	if( bInited == false || !ppNode || !(*ppNode) )
		return;

	if( (*((LunaLog::MemoryData<K>**)ppNode))->bOverdraft != NULL )
		RecycleOverdraftNode( hAssistantHeap, &pActiveOverdraftLink, (LunaLog::MemoryData<K>**)ppNode );
	else
		RecycleNode( &pRecycleLink, &pActiveLink, (LunaLog::MemoryData<K>**)ppNode );
}

template <typename K>
void LunaLog::TMemoryPoolCore<K>::Recycle( K* & pNode )
{
	if( bInited == false || !pNode )
		return;

	if( ((LunaLog::MemoryData<K>*)pNode)->bOverdraft != NULL )
		RecycleOverdraftNode( hAssistantHeap, &pActiveOverdraftLink, (LunaLog::MemoryData<K>**)&pNode );
	else
		RecycleNode( &pRecycleLink, &pActiveLink, (LunaLog::MemoryData<K>**)&pNode );
}

/*===========================================================================

FUNCTION: LunaLog::TMemoryPoolCore::GetStatus

DESCRIPTION:
	Get the memory blocks counters.

PARAMETERS:
	strMPS [in] - The memory blocks counters unit.

RETURN VALUE:
   None
===========================================================================*/
template <typename K>
inline void LunaLog::TMemoryPoolCore<K>::GetStatus( LunaLog::MemoryPoolStatus &strMPS )
{
	if( bInited == false )
	{
		ZeroMemory( &strMPS, sizeof MemoryPoolStatus );
		return;
	}

	GetStatusSnapshot(strMPS);
}

//-- May not be accurate, but very fast, and do not affect performance.
template <typename K>
inline void LunaLog::TMemoryPoolCore<K>::GetStatusSnapshot(LunaLog::MemoryPoolStatus &strMPS)
{
	strMPS.ulMaxNumber = ulMaxNum;
	strMPS.ulPerIncNumber = ulIncNum;
	strMPS.ulPerfectNumber = ulPerfectNum;
	strMPS.ulUsedNumber = ulUsedNum;
	strMPS.ulFreeNumber = ulFreeNum;
	strMPS.ulOverdraftNumber = ulOverdraftNumber;
	strMPS.ulTotalUsedNumber = ulUsedNum + ulOverdraftNumber;
	strMPS.ulTotalNumber = ulTotalNum;
}

#endif // _LUNA_LOG__TMEMORY_POOL_CORE_H_
